#ifndef XTF_EXAMPLE_TRADER_H
#define XTF_EXAMPLE_TRADER_H

#include <cstdlib>
#include <cstring>
#include <string>

#include "XTFApi.h"

const int kTraderInited = 0;
const int kTraderStarted = 1;
const int kTraderLoggedIn = 2;
const int kTraderReadyForTrading = 3;
const int kTraderLoadFinished = 4;
const int kTraderLoggedOut = 5;
const int kTraderStopped = 6;

class ExampleTrader : public XTFSpi
{
public:
    ExampleTrader() = default;
    ~ExampleTrader() override = default;

    void setUsername(const std::string &value) { mUsername = value; }
    void setPassword(const std::string &value) { mPassword = value; }
    void setAppID(const std::string &value) { mAppID = value; }
    void setAuthCode(const std::string &value) { mAuthCode = value; }
    void setConfigPath(const std::string &value) { mConfigPath = value; }
    void setInstrumentID(const std::string &value) { mInstrumentID = value; }
    void setPrice(double price) { mPrice = price; }
    void setVolume(int volume) { mVolume = volume; }

    void onStart(int errorCode, bool isFirstTime) override { mStatus = kTraderStarted; }
    void onStop(int errorCode) override { mStatus = kTraderStopped; }
    void onLogin(int errorCode, int exchangeCount) override { mStatus = kTraderLoggedIn; }
    void onLogout(int errorCode) override { mStatus = kTraderLoggedOut; }
    void onChangePassword(int errorCode) override {}
    void onReadyForTrading(const XTFAccount *account) override { mStatus = kTraderReadyForTrading; }
    void onLoadFinished(const XTFAccount *account) override { mStatus = kTraderLoadFinished; }
    void onOrder(int errorCode, const XTFOrder *order) override {}
    void onCancelOrder(int errorCode, const XTFOrder *cancelOrder) override {}
    void onTrade(const XTFTrade *trade) override {}
    void onAccount(int event, int action, const XTFAccount *account) override {}
    void onExchange(int event, int channelID, const XTFExchange *exchange) override {}
    void onInstrument(int event, const XTFInstrument *instrument) override {}
    void onBookUpdate(const XTFMarketData *marketData) override {}
    void onEvent(const XTFEvent &event) override {}
    void onError(int errorCode, void *data, size_t size) override {}

    bool isStarted() const {
        return mStatus == kTraderStarted
               || mStatus == kTraderLoggedIn
               || mStatus == kTraderReadyForTrading
               || mStatus == kTraderLoadFinished
               || mStatus == kTraderLoggedOut;
    }
    bool isLoggedIn() const {
        return mStatus == kTraderLoggedIn
               || mStatus == kTraderReadyForTrading
               || mStatus == kTraderLoadFinished;
    }
    bool isReadyForTrading() const {
        return mStatus == kTraderReadyForTrading
               || mStatus == kTraderLoadFinished;
    }
    bool isLoadFinished() const {
        return mStatus == kTraderLoadFinished;
    }
    bool isLoggedOut() const {
        return mStatus == kTraderLoggedOut
               || mStatus == kTraderStopped;
    }
    bool isStopped() const {
        return mStatus == kTraderStopped;
    }

    void wait(int seconds, const char *tips) {
        if (seconds <= 0) return;
        if (seconds >= 3600) seconds = 3600;
        if (tips) printf("%s, sleep %d second(s).\n", tips, seconds);
        sleep(seconds);
    }

    const char* getOrderStatus(XTFOrderStatus status) {
        switch (status) {
            case XTF_OS_Created: return "created";
            case XTF_OS_Accepted: return "accepted";
            case XTF_OS_Queuing: return "queuing";
            case XTF_OS_PartTraded: return "part-traded";
            case XTF_OS_AllTraded: return "all-traded";
            case XTF_OS_Canceled: return "canceled";
            case XTF_OS_Rejected: return "rejected";
            default: return "unknown";
        }
    }

protected:
    XTFApi *mApi = nullptr;
    std::string mUsername;
    std::string mPassword;
    std::string mAppID;
    std::string mAuthCode;
    std::string mConfigPath;
    std::string mInstrumentID;
    double      mPrice = 0.0f;
    uint32_t    mVolume = 0;
    int         mStatus = kTraderInited;
};

#endif
